(function($) {
    
	if (typeof($) === 'undefined' || typeof($.ui) === 'undefined') {
		throw 'Requires jQuery and jQuery UI';
	}

    jqkit.components.Panel = function(element) {
	    var self = this;
        
		if (jqkit.isDefinedAndNotNull(element) === false) {
			throw 'Html element parameter is not defined';
		}
		
		if (element instanceof $ === false) {
			element = $(element);
		}
		
		if (element.hasClass('vc-pnl') === false) {
			throw 'Html element parameter is not a valid panel component wrapper.';
		}

        self.wrapper_ = element;

        self.wrapper_.data('jqkit.components.panel', self);
    };

    jqkit.components.Panel.prototype.wrapper_;

    jqkit.components.Panel.prototype.isCollapsible = function() {
        return (
            this.wrapper_.hasClass('vc-pnl-collapsible') === true
        );
    };

    jqkit.components.Panel.prototype.isCollapsed = function() {
        return (
            this.wrapper_.hasClass('vc-pnl-collapsible') === true && 
            this.wrapper_.hasClass('vc-pnl-collapsed') === true
        );
    };

    jqkit.components.Panel.prototype.toggle = function() {
        var self = this;
        if (self.isCollapsible() === false) {
            return;
        }
        if (self.isCollapsed() === true) {
            self.expand();
        } else {
            self.collapse();
        }
    };

    jqkit.components.Panel.prototype.expand = function() {
        var self = this;

        if (self.isCollapsible() === false) {
            return;
        }
        
        var onBeforeExpand = self.wrapper_.attr('data-before-expand');
        if (typeof(onBeforeExpand) !== 'undefined') {
            if (jqkit.executeByName.call(self.wrapper_, onBeforeExpand) === false) {
                return false;
            }
        }

        self.wrapper_.removeClass('vc-pnl-collapsed').children('div.vc-pnl-bodyWrap').show();
    };

    jqkit.components.Panel.prototype.collapse = function() {
        var self = this;

        if (self.isCollapsible() === false) {
            return;
        }
        
        var onBeforeCollapse = self.wrapper_.attr('data-before-collapse');
        if (typeof(onBeforeCollapse) !== 'undefined') {
            if (jqkit.executeByName.call(self.wrapper_, onBeforeCollapse) === false) {
                return false;
            }
        }

        self.wrapper_.addClass('vc-pnl-collapsed').children('div.vc-pnl-bodyWrap').hide();
    };
    
    jqkit.components.Panel.initialize = function() {
        $('body').delegate('.vc-pnl-header', 'click', function(event) {
            // Prevent content toggle if click was triggered from certain elements.
            if (event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'input') {
                return;
            }
            var pnlElem = $(this).closest('div.vc-pnl'), pnl = pnlElem.data('jqkit.components.panel');
            // Make sure panel is initialized.
            if (typeof(pnl) === 'undefined') {
                pnl = new jqkit.components.Panel(pnlElem);
            }
            // Toggle panel content.
            pnl.toggle();
            // Prevent further propagation.
            event.stopPropagation();
        });
    };

    $(document).ready(function() {
        jqkit.components.Panel.initialize();
    });

})(jQuery);